<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * This file contains several helper functions for arrays. The following
 * functions are defined:
 *
 * - assert_valid_keys
 * - is_assoc
 * - is_within
 *
 * PHP version 5
 *
 * This file is part of Majic - A rapid-development web application framework
 * for PHP 5.
 *
 * Majic is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Majic is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Majic. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package     Majic
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright   2007-2008 Michael J. I. Jackson
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
 * @version     SVN: $Id: array.php 36 2008-08-09 23:31:49Z mjijackson $
 */

/**
 * Asserts that each key in the array is also present in valid_keys. Throws
 * an exception if array contains an invalid key.
 *
 * @param   array   $array          The array to check
 * @param   array   $valid_keys     An array containing valid key names
 * @return  void
 * @throws  Exception
 * @access  public
 */
function assert_valid_keys($array, $valid_keys)
{
    $invalid_keys = array();
    foreach (array_keys($array) as $key) {
        if (!in_array($key, $valid_keys)) {
            $invalid_keys[] = $key;
        }
    }

    if (count($invalid_keys) > 0) {
        throw new Exception('Invalid key(s): ' . implode(', ', $invalid_keys));
    }
}

/**
 * Tells whether an array is associative or not. In order to be non-associative,
 * each of the array's key numbers must correspond exactly to it's position
 * in the array.
 *
 * @param   array   $array      The array to check
 * @return  bool                True if the array is associative
 * @access  public
 */
function is_assoc($array)
{
    return is_array($array) && count($array) !== array_reduce(array_keys($array), 'callback_is_assoc', 0);
}

/**
 * @ignore
 */
function callback_is_assoc($a, $b)
{
    return $a === $b ? $a + 1 : 0;
}

/**
 * Checks to see if a numeric value is within a given range of numbers. The
 * maximum and minimum from the provided range will be used.
 *
 * @param   mixed   $value          The value to test
 * @param   array   $range          A range of numbers
 * @param   bool    $inclusive      True to test the max and min inclusively
 * @return  bool                    True if the value is within the range
 * @access  public
 */
function is_within($value, $range, $inclusive = true)
{
    $max = max($range);
    $min = min($range);

    if ($inclusive === true) {
        return $min <= $value && $value <= $max;
    } else {
        return $min < $value && $value < $max;
    }
}

?>
